package ca.tatham.senssim.diffusion;

import ca.tatham.senssim.AbstractPacket;
import ca.tatham.senssim.SensorType;
import ca.tatham.senssim.Simulation;
import ca.tatham.senssim.util.Address;

public class DataMessage extends AbstractPacket
{
  private final Address m_originalSource;
  private final SensorType m_type;
  private final long m_sourceTime;
  private long m_receiveTime = 0;
  private int m_receiveCount = 0;

  public DataMessage(Address sinkAddress, Address source, Address destination,
      SensorType type)
  {
    super(source, destination, sinkAddress);
    m_type = type;
    m_originalSource = source;
    m_sourceTime = Simulation.getTime();
  }

  public DataMessage(Address source, Address destination, SensorType type)
  {
    this((Address) null, source, destination, type);
  }

  public DataMessage(DataMessage packet, Address newSource,
      Address newDestination)
  {
    super(newSource, newDestination, packet.getSinkAddress(), packet
        .getSequence());
    m_originalSource = packet.getOriginalSource();
    m_type = packet.getType();
    m_sourceTime = packet.getSourceTime();
  }

  public Address getOriginalSource()
  {
    return m_originalSource;
  }

  public void received()
  {
    int time = Simulation.getTime();
    if (m_receiveTime == 0)
    {
      m_receiveTime = time;
    }
    m_receiveCount++;
  }

  public int getReceiveCount()
  {
    return m_receiveCount;
  }

  public long getReceiveTime()
  {
    return m_receiveTime;
  }

  public long getSourceTime()
  {
    return m_sourceTime;
  }

  public SensorType getType()
  {
    return m_type;
  }

  public int getSize()
  {
    return 128;
  }

  @Override
  public boolean equals(Object obj)
  {
    DataMessage that = (DataMessage) obj;
    return this.m_sourceTime == that.m_sourceTime
        && this.getSequence() == that.getSequence()
        && this.m_type.equals(that.m_type)
        && this.getSource().equals(that.getSource());
  }

  @Override
  public int hashCode()
  {
    return (int) (m_type.hashCode() ^ m_sourceTime);
  }

  @Override
  public String toString()
  {
    return "DataMessage: #" + getSequence() + " " + getType()
        + " destined for " + getDestination();
  }
}
